import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @Author: biubiu0002
 * @Date: 2021-05-18 17:23
 **/
public class Controller {
    public File selectedFile;
    public Image currentImage;
    public Mat currentMat;
    public Mat beginMat;






    @FXML
    private ImageView myImageView;

    @FXML
    public Label myLabel;

    @FXML
    private AnchorPane mainPane;

    private Mat img = null;
    private Mat Histimg= null;
    private Mat imgHSV = null;
    private Mat imgResult = null;
    private Mat imgGray = null;
    private Mat opening = null;
    private Mat imgGauss = null;
    private Mat imgthres = null;
    private List<MatOfPoint> contours=null;

    public void HIST(ActionEvent event){
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        img= Imgcodecs.imread(selectedFile.getAbsolutePath());
        List<Mat> channel = new ArrayList<Mat>();
        Core.split(img,channel);// channel has 3 elements
        //System.out.println(channel);
        Mat dst1 = new Mat();
        Mat dst2 = new Mat();
        Mat dst3 = new Mat();
        List<Mat> dst = new ArrayList<Mat>();
        Imgproc.equalizeHist(channel.get(0), dst1); // src 原图，dst 直方图均衡化后的结果
        Imgproc.equalizeHist(channel.get(1), dst2); // src 原图，dst 直方图均衡化后的结果
        Imgproc.equalizeHist(channel.get(2), dst3); // src 原图，dst 直方图均衡化后的结果
        dst.add(dst1);
        dst.add(dst2);
        dst.add(dst3);
        Histimg = new Mat();
//        HighGui.imshow("均衡化1",dst1);
//        HighGui.imshow("均衡化2",dst2);
//        HighGui.imshow("均衡化3",dst3);
        Core.merge(dst,Histimg);
//        HighGui.imshow("直方图均衡化",Histimg);
//        HighGui.waitKey();
        currentMat = Histimg;
        currentImage = convertMat2Image(Histimg);
        myImageView.setImage(currentImage);
        myLabel.setText("");


    }

    public void convert2HSV(){
        imgHSV = new Mat();
        Imgproc.cvtColor(Histimg, imgHSV, Imgproc.COLOR_BGR2HSV);
        currentMat = imgHSV;
        currentImage = convertMat2Image(imgHSV);
        myImageView.setImage(currentImage);
        myLabel.setText("");

    }

    public void makeMask(ActionEvent event){
        Mat mask = new Mat();
        Core.inRange(imgHSV,new Scalar(5,0,188),new Scalar(29,255,255),mask);
        imgResult = new Mat();
        Core.bitwise_and(imgHSV,imgHSV,imgResult,mask);
        currentMat = imgResult;
        currentImage = convertMat2Image(imgResult);
        myImageView.setImage(currentImage);
        myLabel.setText("");
    }

    public void makeGray(ActionEvent event){
        // -----灰度化
        imgGray = new Mat();
        Imgproc.cvtColor(imgResult,imgGray,Imgproc.COLOR_BGR2GRAY);
        currentMat = imgGray;
        currentImage = convertMat2Image(imgGray);
        myImageView.setImage(currentImage);
        myLabel.setText("");
    }

    public void openProcess(){
        opening= new Mat();
        Mat kernel=Imgproc.getStructuringElement(Imgproc.CV_SHAPE_CROSS, new Size(3,3));
        Imgproc.morphologyEx(imgGray,opening,Imgproc.MORPH_OPEN, kernel);
        currentMat = opening;
        currentImage = convertMat2Image(opening);
        myImageView.setImage(currentImage);
        myLabel.setText("");
    }

    public void gaussianBlur(){
        imgGauss = new Mat();
        Imgproc.GaussianBlur(opening,imgGauss,new Size(5,5),3);
        currentMat = imgGauss;
        currentImage = convertMat2Image(imgGauss);
        myImageView.setImage(currentImage);
        myLabel.setText("");
    }

    public void threshold(){
        imgthres = new Mat();
        Imgproc.threshold(imgGauss,imgthres,80,255,Imgproc.THRESH_BINARY);
        currentMat = imgthres;
        currentImage = convertMat2Image(imgthres);
        myImageView.setImage(currentImage);
        myLabel.setText("");
    }

    public void contoursDetect(){
        contours = new ArrayList<MatOfPoint>() ;
        Mat hierarchy = new Mat();
        Mat imgContours= Imgcodecs.imread(selectedFile.getAbsolutePath());
        Imgproc.findContours(imgthres, contours,hierarchy,Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
        int i = 0 ,len=contours.toArray().length;
        while (i<len){
            double area = Imgproc.contourArea(contours.get(i));
            System.out.println(area);//每个轮廓的信息

            if(area>500){
                Imgproc.drawContours(img,contours,i, new Scalar(0, 0, 255), 2);
            }
            i++;
        }
        currentMat = img;
        currentImage = convertMat2Image(img);
        myImageView.setImage(currentImage);
        myLabel.setText("");
    }

    public void drawEdgeAndCountNums(){
        //-------------------标出橘子   需要参数：contours，原图     输出：一张被标记的原图，citrusNum柑橘个数
        int i = 0 ,len=contours.toArray().length;
        double contourArea[] = new double[len];
        double maxArea=0;
        while (i<len){
            contourArea[i] = Imgproc.contourArea(contours.get(i));
            if(maxArea<contourArea[i])
            {
                maxArea=contourArea[i];
            }
            i++;
        }
        i=0;
        int citrusNum = 0;
        while (i<len){
            if(contourArea[i]>maxArea*0.25)
            {   citrusNum++;
                System.out.println(contours.get(i));
                // Imgproc.drawContours(img,contours,i, new Scalar(0, 0, 255), 2);
//               RotatedRect minAreaRect = Imgproc.minAreaRect( new MatOfPoint2f(contours.get(i).toArray()));
                Rect rect = Imgproc.boundingRect(contours.get(i));
                double x = rect.x;
                double y = rect.y;
                double w = rect.width;
                double h = rect.height;
//               System.out.println("宽："+w+"   "+"高"+h+"    ");
                // Imgproc.rectangle(img,new Point(x,y),new Point(x+w,y+h),new Scalar(0,255,0),2);
                double circlex = x+w/2,circley = y+h/2,radius = (circlex+circley)/2;
                MatOfPoint2f newcontours = new MatOfPoint2f();
                contours.get(i).convertTo(newcontours, CvType.CV_32F);
                float r[]=new float[1];
                r[0]=(float)radius;
                Imgproc.minEnclosingCircle(newcontours,new Point(circlex,circley),r);
                Imgproc.circle(beginMat,new Point(circlex,circley),(int)r[0],new Scalar(255,0,0),2);
                currentMat = beginMat;
                currentImage = convertMat2Image(beginMat);
                myImageView.setImage(currentImage);
            }
            i++;
        }
        System.out.println("柑橘个数为： "+citrusNum);
        myLabel.setText("柑橘个数为："+citrusNum);
    }



    public void openImg(ActionEvent event){
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        Window stage = mainPane.getScene().getWindow();
        FileChooser fileChooser = new FileChooser();
        selectedFile = fileChooser.showOpenDialog(stage);
        if(selectedFile!=null){
            beginMat = Imgcodecs.imread(selectedFile.getAbsolutePath());
            Image image = new Image("file:"+selectedFile.getAbsolutePath());
            myImageView.setImage(image);
            initImg();
        }
    }

    public void saveImg(ActionEvent event) throws IOException {
        Window stage = mainPane.getScene().getWindow();
        FileChooser fileChooser = new FileChooser();

        fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("jpg", "*.jpg"),
                new FileChooser.ExtensionFilter("jpeg", "*.jpeg"),
                new FileChooser.ExtensionFilter("bmp", "*.bmp"),
                new FileChooser.ExtensionFilter("Allfiles", "*.*"));
        File file = fileChooser.showSaveDialog(stage);
        String fileName = file.getName();
        //fileParent是文件所在文件夹  ../
        File fileParent = file.getParentFile();
        String fileParentPath = file.getParent();

        System.out.println(file);
        boolean imwrite = false;
        if(currentMat!=null){
            //进行了矩阵操作运算，把矩阵输出成文件。
            imwrite = Imgcodecs.imwrite(file.getAbsolutePath(), currentMat);
            if(imwrite){
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("保存成功");
                alert.setHeaderText("保存成功");
                alert.setContentText("保存成功！");
                alert.showAndWait();
            }else{
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setContentText("保存失败！");
                alert.showAndWait();
            }
        }
        else{
            //刚打开文件 单纯另存为
            if(!fileParent.exists()){
                fileParent.mkdirs();
            }
            if(!file.exists()){
                file.createNewFile();
            }
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("保存成功");
            alert.setHeaderText("保存成功");
            alert.setContentText("保存成功！");
            alert.showAndWait();
        }

    }

    private  void initImg(){
        img = null;
        Histimg= null;
        imgHSV = null;
        imgResult = null;
        imgGray = null;
        opening = null;
        imgGauss = null;
        imgthres = null;
        currentImage=null;
        contours=null;
        myLabel.setText("");
    }

    private Image convertMat2Image(Mat someMat){
        MatOfByte byteMat = new MatOfByte();
        Imgcodecs.imencode(".bmp",someMat,byteMat);

        return new Image(new ByteArrayInputStream(byteMat.toArray()));
    }




}
